﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using BlankMvc.Controllers.Base;
using BlankMvc.Dao.Entities.Impl;
using BlankMvc.Services.Interfaces;
using BlankMvc.Types;
using Microsoft.AspNet.Identity;
//using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin.Security;
using BlankMvc.Models;

namespace BlankMvc.Controllers {
	[Authorize]
	public class AccountController : BaseController {

		public virtual IUserService userService { get; set; }

		//public UserManager<ApplicationUser> UserManager { get; private set; }

		[AllowAnonymous]
		[Title("Авторизация")]
		public ActionResult LoginForm(string returnUrl) {
			ViewBag.ReturnUrl = returnUrl;
			return ViewBase(DIALOG, null, new UserLogin());
		}

		[HttpPost]
		[AllowAnonymous]
		[ValidateAntiForgeryToken]
		[Title("Авторизация")]
		public ActionResult Login(UserLogin model, string returnUrl) {
			if (!ModelState.IsValid)
				return ViewBase(DIALOG, "LoginForm", model);
			//User user = userService.ValidateUser(model.UserName, model.Password);
			//if (user != null) {
			User user = new User {
				Login = "qwe",
				Name = "qwerwer"

			};
			SignInAsync(user, model.RememberMe);
			return RedirectBase("Index", "Home");// ViewBase("#loginButtons", "_LoginPartial");
			//}
			ModelState.AddModelError("", "Неверное имя пользователя или пароль.");
			return ViewBase("#dialogsContainer", "LoginForm", model);
		}

		[Title("Профиль пользователя")]
		[HttpGet]
		public ActionResult ViewProfile() {
			return ViewBase(CONTENT);
		}

		[Title("Изменить фото")]
		public ActionResult CropPicture() {
			return ViewBase(DIALOG);
		}

		//
		// POST: /Account/LogOff
		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult LogOff() {
			AuthenticationManager.SignOut();
			return RedirectToAction("Index", "Home");
		}

		//
		// GET: /Account/Register
		[AllowAnonymous]
		[Title("Регистрация")]
		public ActionResult RegisterForm() {
			return ViewBase("#dialogsContainer", null, new UserRegister());
		}

		//
		// POST: /Account/Register
		[HttpPost]
		[AllowAnonymous]
		[Title("Регистрация")]
		[ValidateAntiForgeryToken]
		public ActionResult Register(UserRegister model) {
			if (ModelState.IsValid) {
				/*User result = userService.Create(model);
				if (result ! = null) {
					SignInAsync(result, isPersistent: false);
					return RedirectToAction("Index", "Home");
				} else {
					AddErrors(result);
				}*/
			}
			return ViewBase("#dialogsContainer", "RegisterForm", model);
		}

		//
		// POST: /Account/Disassociate
		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<ActionResult> Disassociate(string loginProvider, string providerKey) {
			ManageMessageId? message = null;
			/*IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
			if (result.Succeeded) {
				message = ManageMessageId.RemoveLoginSuccess;
			} else {
				message = ManageMessageId.Error;
			}*/
			return RedirectToAction("Manage", new { Message = message });
		}

		//
		// GET: /Account/Manage
		public ActionResult Manage(ManageMessageId? message) {
			ViewBag.StatusMessage =
				message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
				: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
				: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
				: message == ManageMessageId.Error ? "An error has occurred."
				: "";
			ViewBag.HasLocalPassword = HasPassword();
			ViewBag.ReturnUrl = Url.Action("Manage");
			return View();
		}

		//
		// POST: /Account/Manage
		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<ActionResult> Manage(ManageUserViewModel model) {
			bool hasPassword = HasPassword();
			ViewBag.HasLocalPassword = hasPassword;
			ViewBag.ReturnUrl = Url.Action("Manage");
			if (hasPassword) {
				/*if (ModelState.IsValid) {
					IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
					if (result.Succeeded) {
						return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
					} else {
						AddErrors(result);
					}
				}*/
			} else {
				// User does not have a password so remove any validation errors caused by a missing OldPassword field
				ModelState state = ModelState["OldPassword"];
				if (state != null) {
					state.Errors.Clear();
				}

				if (ModelState.IsValid) {
					/*IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
					if (result.Succeeded) {
						return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
					} else {
						AddErrors(result);
					}*/
				}
			}

			// If we got this far, something failed, redisplay form
			return View(model);
		}

		//
		// POST: /Account/LinkLogin
		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult LinkLogin(string provider) {
			// Request a redirect to the external login provider to link a login for the current user
			return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
		}

		//
		// GET: /Account/LinkLoginCallback
		public async Task<ActionResult> LinkLoginCallback() {
			var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
			if (loginInfo == null) {
				return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
			}
			/*var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
			if (result.Succeeded) {
				return RedirectToAction("Manage");
			}*/
			return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
		}

		[ChildActionOnly]
		public ActionResult RemoveAccountList() {
			/*var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
			ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;*/
			return null;// (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
		}

		protected override void Dispose(bool disposing) {
			/*if (disposing && UserManager != null) {
				UserManager.Dispose();
				UserManager = null;
			}*/
			base.Dispose(disposing);
		}

		#region Helpers
		// Used for XSRF protection when adding external logins
		private const string XsrfKey = "XsrfId";

		private IAuthenticationManager AuthenticationManager {
			get {
				return HttpContext.GetOwinContext().Authentication;
			}
		}

		private void SignInAsync(User user, bool isPersistent) {
			AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
			var identity = userService.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
			AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, identity);
		}

		private void AddErrors(IdentityResult result) {
			foreach (var error in result.Errors) {
				ModelState.AddModelError("", error);
			}
		}

		private bool HasPassword() {
			/*var user = UserManager.FindById(User.Identity.GetUserId());
			if (user != null) {
				return user.PasswordHash != null;
			}*/
			return false;
		}

		public enum ManageMessageId {
			ChangePasswordSuccess,
			SetPasswordSuccess,
			RemoveLoginSuccess,
			Error
		}

		private ActionResult RedirectToLocal(string returnUrl) {
			if (Url.IsLocalUrl(returnUrl)) {
				return Redirect(returnUrl);
			} else {
				return RedirectToAction("Index", "Home");
			}
		}

		private class ChallengeResult : HttpUnauthorizedResult {
			public ChallengeResult(string provider, string redirectUri)
				: this(provider, redirectUri, null) {
			}

			public ChallengeResult(string provider, string redirectUri, string userId) {
				LoginProvider = provider;
				RedirectUri = redirectUri;
				UserId = userId;
			}

			public string LoginProvider { get; set; }
			public string RedirectUri { get; set; }
			public string UserId { get; set; }

			public override void ExecuteResult(ControllerContext context) {
				var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
				if (UserId != null) {
					properties.Dictionary[XsrfKey] = UserId;
				}
				context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
			}
		}
		#endregion
	}
}